/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package samoloty.view;

import Utils.DoublePoint;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import javax.swing.JPanel;

/**
 *
 * @author borysfan
 */
public class PlotPanel extends JPanel {

    private int width = 248;
    private int height = 250;
    private int startX = 35;
    private int startY = 255;
    private ArrayList<DoublePoint> fwdPoints = null;
    private ArrayList<DoublePoint> aftPoints = null;
    private ArrayList<DoublePoint> zfwFwdPoints = null;
    private ArrayList<DoublePoint> zfwAftPoints = null;
    private double xScale = 1;
    private double yScale = 1;
    private double minPlotX;
    private double minPlotY;
    //DOW
    private double vdoi_x;
    private double vdow_y;

    //ZFW
    private double vzfwi_x;
    private double vazfw_y;

    //TOW
    private double vtowi_x;
    private double vatow_y;

    //x, vlavi  y-vlaw
    private double vlavi_x;
    private double valaw_y;

    private int step;

    public PlotPanel() {
        super();
        initPanel();
    }

    public void setFwdPoints(ArrayList<DoublePoint> points) {
        fwdPoints = points;
    }

    public void setAftPoints(ArrayList<DoublePoint> points) {
        aftPoints = points;
    }

    private void initPanel() {
        this.setBackground(MyColors.getBlack());
        this.setOpaque(true);
    }

    @Override
    public void paint(Graphics g) {
        super.paint(g);
        drawPlot(g);
    }

    public void drawPlot(Graphics g) {

        //dlugosc osi Y=250 piksli
        //szerokosc X:248 piksli
        //System.out.println(35 + " "+ 5+" " + 35+" " + (getHeight()-35));
        //System.out.println(35+ " "+(getHeight()-35) + " " +(getWidth()-5)+ " " +(getHeight()-35));
        g.setColor(MyColors.getWhite());
        g.drawLine(35, 5, 35, getHeight() - 35);
        g.drawLine(35, getHeight() - 35, getWidth() - 5, getHeight() - 35);
        g.drawLine(30, 10, 35, 5);
        g.drawLine(35, 5, 40, 10);
        g.drawLine(getWidth() - 5, getHeight() - 35, getWidth() - 10, getHeight() - 40);
        g.drawLine(getWidth() - 5, getHeight() - 35, getWidth() - 10, getHeight() - 30);
        g.drawString("INDEX", 125, getHeight() - 2);

        if (aftPoints != null && fwdPoints != null) {
            ArrayList<Integer> xscale = computeXScale();
            ArrayList<Integer> yscale = computeYScale();
            drawXScale(g, xscale);
            drawYScale(g, yscale);

            Collections.sort(fwdPoints, new Comparator() {

                public int compare(Object o1, Object o2) {
                    DoublePoint pointa = (DoublePoint) o1;
                    DoublePoint pointb = (DoublePoint) o2;
                    if (pointa.y > pointb.y) {
                        return -1;
                    } else if (pointa.y == pointb.y) {
                        return 0;
                    } else {
                        return 1;
                    }
                }
            });

            Collections.sort(aftPoints, new Comparator() {

                public int compare(Object o1, Object o2) {
                    DoublePoint pointa = (DoublePoint) o1;
                    DoublePoint pointb = (DoublePoint) o2;
                    if (pointa.y > pointb.y) {
                        return -1;
                    } else if (pointa.y == pointb.y) {
                        return 0;
                    } else {
                        return 1;
                    }
                }
            });

            Collections.sort(zfwAftPoints, new Comparator() {

                public int compare(Object o1, Object o2) {
                    DoublePoint pointa = (DoublePoint) o1;
                    DoublePoint pointb = (DoublePoint) o2;
                    if (pointa.y > pointb.y) {
                        return -1;
                    } else if (pointa.y == pointb.y) {
                        return 0;
                    } else {
                        return 1;
                    }
                }
            });

            Collections.sort(zfwFwdPoints, new Comparator() {

                public int compare(Object o1, Object o2) {
                    DoublePoint pointa = (DoublePoint) o1;
                    DoublePoint pointb = (DoublePoint) o2;
                    if (pointa.y > pointb.y) {
                        return -1;
                    } else if (pointa.y == pointb.y) {
                        return 0;
                    } else {
                        return 1;
                    }
                }
            });

            g.setColor(new Color(0, 255, 0));

            //drawPoints(g, fwdPoints);
            //drawPoints(g, aftPoints);

            ArrayList<Point> computedFwdPoints = computePoints(fwdPoints);
            ArrayList<Point> computedAftPoints = computePoints(aftPoints);
            g.drawLine(computedFwdPoints.get(0).x, computedFwdPoints.get(0).y, computedAftPoints.get(0).x, computedAftPoints.get(0).y);
            g.drawLine(computedFwdPoints.get(computedFwdPoints.size() - 1).x, computedFwdPoints.get(computedFwdPoints.size() - 1).y, computedAftPoints.get(computedFwdPoints.size() - 1).x, computedAftPoints.get(computedFwdPoints.size() - 1).y);
            Point first = computedFwdPoints.get(0);
            g.drawString("MTOW", first.x - 40, first.y);
            for (int i = 1; i < computedFwdPoints.size(); i++) {
                Point second = computedFwdPoints.get(i);
                g.drawLine(first.x, first.y, second.x, second.y);
                first = second;
            }

            first = computedAftPoints.get(0);
            for (int i = 1; i < computedAftPoints.size(); i++) {
                Point second = computedAftPoints.get(i);
                g.drawLine(first.x, first.y, second.x, second.y);
                first = second;
            }

            g.setColor(new Color(0, 66, 0));
            ArrayList<Point> computedZfwFwdPoints = computePoints(zfwFwdPoints);
            ArrayList<Point> computedZfwAftPoints = computePoints(zfwAftPoints);
            g.drawLine(computedZfwFwdPoints.get(0).x, computedZfwFwdPoints.get(0).y, computedZfwAftPoints.get(0).x, computedZfwAftPoints.get(0).y);
            g.drawLine(computedZfwFwdPoints.get(computedZfwFwdPoints.size() - 1).x, computedZfwFwdPoints.get(computedZfwFwdPoints.size() - 1).y, computedZfwAftPoints.get(computedZfwAftPoints.size() - 1).x, computedZfwAftPoints.get(computedZfwAftPoints.size() - 1).y);

            first = computedZfwFwdPoints.get(0);
            g.drawString("MZFW", first.x - 40, first.y);
            for (int i = 1; i < computedZfwFwdPoints.size(); i++) {
                Point second = computedZfwFwdPoints.get(i);
                g.drawLine(first.x, first.y, second.x, second.y);
                first = second;
            }

            first = computedZfwAftPoints.get(0);
            for (int i = 1; i < computedZfwAftPoints.size(); i++) {
                Point second = computedZfwAftPoints.get(i);
                g.drawLine(first.x, first.y, second.x, second.y);
                first = second;
            }

        }
        
        Point p1 = drawX(this.vdoi_x, this.vdow_y);
        if(p1.x > startX && p1.y<startY){
            g.setColor(Color.red);
            g.drawLine(p1.x-5, p1.y+5, p1.x+5,p1.y-5);
            g.drawLine(p1.x+5, p1.y+5, p1.x-5,p1.y-5);
            g.drawString( "DOW",p1.x-20, p1.y+16);
        }
        Point p2 = drawX(this.vtowi_x,this.vatow_y);
        if(p2.x > startX && p2.y<startY){
            g.setColor(Color.blue);
            g.drawLine(p2.x-5, p2.y+5, p2.x+5,p2.y-5);
            g.drawLine(p2.x+5, p2.y+5, p2.x-5,p2.y-5);
            g.drawString( "TOW",p2.x-5, p2.y+16);
        }
        Point p3 = drawX(this.vzfwi_x,this.vazfw_y);
        if(p3.x > startX && p3.y<startY){
            g.setColor(Color.yellow);
            g.drawLine(p3.x-5, p3.y+5, p3.x+5,p3.y-5);
            g.drawLine(p3.x+5, p3.y+5, p3.x-5,p3.y-5);
            g.drawString( "ZFW",p3.x+5, p3.y+16);
        }

        Point p4 = drawX(vlavi_x,valaw_y); //x, vlavi  y-vlaw
        if(p3.x > startX && p4.y<startY){
            g.setColor(Color.pink);
            g.drawLine(p4.x-5, p4.y+5, p4.x+5,p4.y-5);
            g.drawLine(p4.x+5, p4.y+5, p4.x-5,p4.y-5);
            g.drawString( "LAW",p4.x+5, p4.y+16);
        }
        g.setColor(new Color(255, 255, 255));
        Graphics2D g2 = (Graphics2D) g;
        g2.rotate(270.0 * Math.PI / 180.0);
        g2.drawString("WEIGHT",-150,11);

        //double vdoi_x =
        
    }

    public void drawXScale(Graphics g, ArrayList<Integer> labels) {
        int x = 35;
        int range = labels.get(labels.size() - 1) - labels.get(0);
        double offset = width / range;
        xScale = offset;
        for (int i = 0; i < labels.size(); i++) {
            g.drawLine(x, getHeight() - 30, x, getHeight() - 35);
            String s = Integer.toString(labels.get(i));
            g.drawString(s, x - 7, getHeight() - 15);
            x += (offset * 10);
        }
    }

    public void drawYScale(Graphics g, ArrayList<Integer> labels) {
        int y = getHeight() - 35;
        int absoluteStart = y;
        int range = (labels.get(labels.size() - 1) - labels.get(0));
        double offset = height / range;
        yScale = offset;
        System.out.println(labels.get(labels.size() - 1));
        for (int i = 0; i < labels.size(); i++) {
            g.drawLine(30, y, 35, y);
            String s = Integer.toString(labels.get(i));
            g.drawString(s, 9, y + 5);
            y -= (offset*step );
        }
    }

    public ArrayList<Point> computePoints(ArrayList<DoublePoint> points) {
        ArrayList<Point> result = new ArrayList<Point>();
        for (int i = 0; i < points.size(); i++) {
            int x = (int) Math.round((points.get(i).x - minPlotX) * xScale);
            int y = (int) Math.round(((points.get(i).y) / 1000 - minPlotY) * yScale);
           // System.out.println("x="+points.get(i).x+" y="+points.get(i).y);
            x += startX;
            y = startY - y;
            
            result.add(new Point(x, y));
        }
        return result;
    }

    public void drawPoints(Graphics g, ArrayList<DoublePoint> points) {
        g.setColor(new Color(0, 255, 0));
        for (int i = 0; i < points.size(); i++) {
            int x = (int) Math.round((points.get(i).x - minPlotX) * xScale);
            int y = (int) Math.round(((points.get(i).y) / 1000 - minPlotY) * yScale);
            
            //System.out.println(yScale);
            x += startX;
            y = startY - y;
           
            g.drawLine(x, y, x + 1, y);
        }
    }

    public void update() {
        /*
         * obliczyc zakres x
         * obliczyc zakres y
         * obliczyc jakos ilosc podzialek dla osi x skok jest co 10, natomiast dla osi y skok jest co 1
         * na tej podstawie stworzyc labele dla osi x oraz y
         * obliczyc przelicznik
         * naniesc punkty
         */
           this.repaint();
    }

    private double findMinX(ArrayList<DoublePoint> points) {
        double result = 0;
        if (points.size() > 0) {
            result = points.get(0).x;
            for (int i = 1; i < points.size(); i++) {
                result = Math.min(result, points.get(i).x);
            }
        }
        return result;
    }

    private double findMaxX(ArrayList<DoublePoint> points) {
        double result = 0;
        if (points.size() > 0) {
            result = points.get(0).x;
            for (int i = 1; i < points.size(); i++) {
                result = Math.max(result, points.get(i).x);
            }
        }
        return result;
    }

    private double findMinY(ArrayList<DoublePoint> points) {
        double result = 0;
        if (points.size() > 0) {
            result = points.get(0).y;
            for (int i = 1; i < points.size(); i++) {
                result = Math.min(result, points.get(i).y);
            }
        }
        return result;
    }

    private double findMaxY(ArrayList<DoublePoint> points) {
        double result = 0;
        if (points.size() > 0) {
            result = points.get(0).y;
            for (int i = 1; i < points.size(); i++) {
                result = Math.max(result, points.get(i).y);
            }
        }
        return result;
    }

    private ArrayList<Integer> computeXScale() {
        ArrayList<Integer> result = new ArrayList<Integer>();
        double minX = findMinX(fwdPoints);
        double maxX = findMaxX(aftPoints);

        minX = Math.round(minX)-Math.round(minX)%10;
        maxX += 10;
        minPlotX = minX;
        for (int i = (int) Math.round(minX); i <= maxX; i += 10) {
            result.add(i);
        }
        return result;
    }

    private ArrayList<Integer> computeYScale() {
        ArrayList<Integer> result = new ArrayList<Integer>();
        
        double minY = (findMinY(fwdPoints)) / 1000;
        double maxY = findMaxY(aftPoints) / 1000;

        minY*=0.95;
        minY = Math.round(minY)-Math.round(minY)%10;
        maxY = Math.round(maxY * 1.05);
        //System.out.println("miny: " + minY + " maxY" + maxY);
        minPlotY = (int) Math.round(minY);
        step = (int) Math.round((maxY-minY)*0.1);
        for (int i = (int) Math.round(minY); i <= maxY; i += step) {
            result.add(i);
        }
        return result;
    }

    private DoublePoint getTopPoint(ArrayList<DoublePoint> points) {
        if (points.size() > 0) {
            DoublePoint top = points.get(0);
            for (int i = 1; i < points.size(); i++) {
                if (points.get(i).y > top.y) {
                    top = points.get(i);
                }
            }
            return top;
        }
        return new DoublePoint(0, 0);

    }

    public void setZfwFwdPoints(ArrayList<DoublePoint> pointsZfwFwd) {
        zfwFwdPoints = pointsZfwFwd;
    }

    public void setZfwAftPoints(ArrayList<DoublePoint> pointsZfwAft) {
        zfwAftPoints = pointsZfwAft;
    }

    public Point drawX(double x, double y){
         int nx = (int) Math.round((x - minPlotX) * xScale);
         int ny = (int) Math.round((((y) / 1000) - minPlotY) * yScale);
         
         nx+=startX;
         ny=startY-ny;
         //System.out.println("x=" + x+" y=" + y+" | "+nx+" "+ny+"   "+minPlotY);
         return new Point(nx,ny);
    }


    public void set_vdoi(double value){
        vdoi_x = value;
    }

    public void set_vdow(double value){
        vdow_y = value;
    }

    public void set_vzfwi(double value){
        vzfwi_x = value;
    }

    public void set_vazfw(double value){
        vazfw_y = value;
    }

    public void set_vtowi(double value){
        vtowi_x = value;
    }

    public void set_vatow(double value){
        vatow_y = value;
    }

    public void set_vlavi(double value){
        vlavi_x = value;
    }

    public void set_valaw(double value){
        valaw_y = value;
    }
}
